package com.ruicar.afs.cloud.admin.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruicar.afs.cloud.admin.api.dto.DeptDto;
import com.ruicar.afs.cloud.admin.entity.*;
import com.ruicar.afs.cloud.admin.service.*;
import com.ruicar.afs.cloud.common.core.security.vo.RoleVo;
import com.ruicar.afs.cloud.common.core.security.vo.UserVo;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
@AllArgsConstructor
public class OrganizationServiceImpl implements IOrganizationService {

    private SysUserService sysUserService;

    private SysRoleService roleService;

    private SysVirtualGroupService sysVirtualGroupService;

    private SysUserVirtualGroupService sysUserVirtualGroupService;

    private SysUserRoleService sysUserRoleService;

    private SysDepartmentService sysDepartmentService;

    @Override
    public UserVo getUserInfoByLoginName(String loginName) {
        SysUser sysUser = sysUserService.getOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getUsername, loginName));
        UserVo userVo = new UserVo();
        userVo.setUsername(sysUser.getUsername());
        userVo.setUserRealName(sysUser.getUserRealName());
        return userVo;
    }

    @Override
    public RoleVo getRoleByCode(String roleCode) {
        SysRole role = roleService.getOne(Wrappers.<SysRole>lambdaQuery().eq(SysRole::getRoleCode, roleCode));
        RoleVo roleVo = new RoleVo();
        roleVo.setRoleCode(role.getRoleCode());
        roleVo.setRoleName(role.getRoleName());
        return roleVo;
    }

    @Override
    public List<RoleVo> getRolesByLoginName(String loginName) {
        SysUser sysUser = sysUserService.getOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getUsername, loginName), false);
        if (sysUser != null) {
            return roleService.findRolesByUserId(sysUser.getUserId())
                    .stream()
                    .map((role) -> {
                        RoleVo roleVo = new RoleVo();
                        roleVo.setRoleCode(role.getRoleCode());
                        roleVo.setRoleName(role.getRoleName());
                        return roleVo;
                    }).collect(Collectors.toList());
        } else {
            return new ArrayList<>();
        }
    }



    private List<UserVo> listUserVo(List<?> userIds){
       return sysUserService
                .list(Wrappers.<SysUser>lambdaQuery().in(SysUser::getUserId, userIds))
                .stream()
                .map(sysUser -> {
                    UserVo userVo = new UserVo();
                    userVo.setUsername(sysUser.getUsername());
                    userVo.setUserRealName(sysUser.getUserRealName());
                    return userVo;
                }).collect(Collectors.toList())
        ;
    }

    @Override
    public List<UserVo> getUsersByVirtualCode(String virtualCode) {

        List<Long> userIds = sysUserVirtualGroupService
                .list(Wrappers.<SysUserVirtualGroup>lambdaQuery().eq(SysUserVirtualGroup::getGroupCode, virtualCode))
                .stream().map(SysUserVirtualGroup::getUserId)
                .distinct()
                .collect(Collectors.toList());
        ;
        return listUserVo(userIds);
    }

    @Override
    public List<UserVo> getUsersByVirtualCodes(List<String> virtualCodes) {
        List<Long> userIds = sysUserVirtualGroupService
                .list(Wrappers.<SysUserVirtualGroup>lambdaQuery().in(SysUserVirtualGroup::getGroupCode, virtualCodes))
                .stream()
                .map(SysUserVirtualGroup::getUserId)
                .distinct()
                .collect(Collectors.toList());
        return listUserVo(userIds);
    }

    @Override
    public List<UserVo> getUsersByLoginNames(List<String> loginNames) {
        return sysUserService
                .list(Wrappers.<SysUser>lambdaQuery().in(SysUser::getUsername, loginNames))
                .stream()
                .map(sysUser -> {
                    UserVo userVo = new UserVo();
                    userVo.setUsername(sysUser.getUsername());
                    userVo.setUserRealName(sysUser.getUserRealName());
                    return userVo;
                }).collect(Collectors.toList())
                ;
    }

    @Override
    public List<UserVo> getUsersByRoleCode(String roleCode) {
        RoleVo roleVo = getRoleByCode(roleCode);
        if(roleVo!=null){
            List<Long> userIds = sysUserRoleService.list(Wrappers.<SysUserRole>lambdaQuery().eq(SysUserRole::getRoleId,roleVo.getRoleId()))
                    .stream()
                    .map(SysUserRole::getUserId)
                    .collect(Collectors.toList());
            return listUserVo(userIds);
        }
        return new ArrayList<>();
    }

    @Override
    public List<UserVo> getUsersByRoleCodes(List<String> roleCodes) {
        List<String> roleIds = roleService
                .list(Wrappers.<SysRole>lambdaQuery().in(SysRole::getRoleCode,roleCodes))
                .stream()
                .map(SysRole::getId)
                .map(value->String.valueOf(value))
                .collect(Collectors.toList());
                ;
         List<Long> userIds = sysUserRoleService
                 .list(Wrappers.<SysUserRole>lambdaQuery().in(SysUserRole::getRoleId,roleIds))
                 .stream()
                 .map(SysUserRole::getUserId)
                 .collect(Collectors.toList());

        return listUserVo(userIds);
    }

    @Override
    public List<String> getUserLoginNamesByRoleCodes(List<String> roleCodes) {
        List<String> roleIds = roleService
                .list(Wrappers.<SysRole>lambdaQuery().in(SysRole::getRoleCode,roleCodes))
                .stream()
                .map(SysRole::getId)
                .map(value->String.valueOf(value))
                .collect(Collectors.toList());
        ;
        List<Long> userIds = sysUserRoleService
                .list(Wrappers.<SysUserRole>lambdaQuery().in(SysUserRole::getRoleId,roleIds))
                .stream()
                .map(SysUserRole::getUserId)
                .collect(Collectors.toList());
        return listUserVo(userIds).stream().map(UserVo::getUsername).distinct().collect(Collectors.toList());
    }

    @Override
    public List<String> getUserLoginNamesByVirtualCodes(List<String> deptIds) {
       return sysUserService
                .list(Wrappers.<SysUser>lambdaQuery().in(SysUser::getDeptId,deptIds))
                .stream()
                .map(SysUser::getUsername)
                .distinct()
                .collect(Collectors.toList());
    }

    @Override
    public List<UserVo> getAllUsers() {
        return sysUserService.list().stream().map(sysUser -> {
            UserVo userVo = new UserVo();
            userVo.setUsername(sysUser.getUsername());
            userVo.setUserRealName(sysUser.getUserRealName());
            return userVo;
        }).collect(Collectors.toList());
    }

    @Override
    public List<DeptDto> getDepartment(String param, int startNum, int pageSize) {
        return sysDepartmentService
                .page(new Page<>(startNum,pageSize),Wrappers.<SysDepartment>lambdaQuery().like(StringUtils.isNotEmpty(param),SysDepartment::getTitle,param))
                .getRecords()
                .stream()
                .distinct()
                .map(sysDepartment -> {
                    DeptDto deptDto = new DeptDto();
                    deptDto.setId(Long.valueOf(sysDepartment.getId()));
                    deptDto.setTitle(sysDepartment.getTitle());
                    return deptDto;
                }).collect(Collectors.toList());
    }

    @Override
    public long getDepartmentCount(String param) {
        return sysDepartmentService
                .count(Wrappers.<SysDepartment>lambdaQuery().like(StringUtils.isNotEmpty(param),SysDepartment::getTitle,param));
    }

    @Override
    public List<UserVo> getUsersByDepartment(String departmentId) {
        return sysUserService
                .list(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getDeptId,departmentId))
                .stream()
                .map(sysUser -> {
                    UserVo userVo = new UserVo();
                    userVo.setUsername(sysUser.getUsername());
                    userVo.setUserRealName(sysUser.getUserRealName());
                    return userVo;
                }).collect(Collectors.toList());
    }

    @Override
    public List<String> getLoginNamesByDepartmentId(String departmentId) {
        return  sysUserService
                .list(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getDeptId,departmentId))
                .stream()
                .map(SysUser::getUsername)
                .collect(Collectors.toList());
    }

    @Override
    public DeptDto getDepartment(String id) {
        SysDepartment sysDepartment = sysDepartmentService.getById(id);
        if(sysDepartment!=null){
            DeptDto deptDto = new DeptDto();
            deptDto.setId(Long.valueOf(sysDepartment.getId()));
            deptDto.setTitle(sysDepartment.getTitle());
            return deptDto;
        }
        return null;
    }
}
